home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / vol11n08.zip / DEMO7.C < prev    next >
Text File  |  1992-02-08  |  27KB  |  631 lines

  1. // DEMO7.C --- Pen-centric Windows application that accepts 
  2. //             handwritten input, then displays the contents of
  3. //             the RCRESULT structure, the enumerated symbol
  4. //             strings, or the symbol graph.
  5. // Copyright (C) 1992 Ray Duncan
  6.  
  7. #define WIN31
  8. #define dim(x) (sizeof(x) / sizeof(x[0]))   // returns no. of elements
  9. #define BUFMAX 80                           // size of scratch buffers
  10.  
  11. #include "windows.h"
  12. #include "penwin.h"
  13. #include "demo7.h"
  14.  
  15. HANDLE hInst;                               // instance handle
  16. HWND hWndFrame = 0;                         // frame window handle
  17. HWND hWndText = 0;                          // child text window handle
  18. HWND hWndWrite = 0;                         // child writing window handle
  19. HANDLE hPenWin = 0;                         // Pen Windows module handle
  20.  
  21. int CharX = 0;                              // average char width
  22. int CharY = 0;                              // char height
  23. int CurLine = 0;                            // current line number
  24. int MaxLine = 0;                            // lines per window
  25. int EnumCount = 0;                          // translation counter
  26. int DisplayMode = IDM_RCRESULT;             // current display format
  27.  
  28. char szFrameClass[] = "DemoFrameClass";     // name of frame window class
  29. char szTextClass[]  = "DemoTextClass";      // child text window class
  30. char szWriteClass[] = "DemoWriteClass";     // child writing window class
  31.  
  32. struct decodeInt {                          // simple structure to
  33.     int Code;                               // associate integer values
  34.     char * Name; };                         // with character strings
  35.  
  36. struct decodeSYV {                          // simple structure to
  37.     SYV Code;                               // associate SYV values
  38.     char * Name; };                         // with character strings
  39.  
  40. struct decodeInt recogResults[] = {         // values returned by
  41.     REC_OK, "REC_OK",                       // Recognize() function
  42.     REC_ABORT, "REC_ABORT",
  43.     REC_ALC, "REC_ALC",
  44.     REC_BADEVENTREF, "REC_BADEVENTREF",
  45.     REC_BADHPENDATA, "REC_BADHPENDATA",
  46.     REC_BUFFERTOOSMALL, "REC_BUFFERTOOSMALL",
  47.     REC_BUSY, "REC_BUSY",
  48.     REC_CLVERIFY, "REC_CLVERIFY",
  49.     REC_DICT, "REC_DICT",
  50.     REC_DONE, "REC_DONE",
  51.     REC_ERRORLEVEL, "REC_ERRORLEVEL",
  52.     REC_GUIDE, "REC_GUIDE",
  53.     REC_HREC, "REC_HREC",
  54.     REC_HWND, "REC_HWND",
  55.     REC_INVALIDREF, "REC_INVALIDREF",
  56.     REC_LANGUAGE, "REC_LANGUAGE",
  57.     REC_NOCOLLECTION, "REC_NOCOLLECTION",
  58.     REC_NOINPUT, "REC_NOINPUT",
  59.     REC_NOTABLET, "REC_NOTABLET",
  60.     REC_OEM, "REC_OEM",
  61.     REC_OOM, "REC_OOM",
  62.     REC_OVERFLOW, "REC_OVERFLOW",
  63.     REC_PARAMERROR, "REC_PARAMERROR",
  64.     REC_PCM, "REC_PCM",
  65.     REC_POINTEREVENT, "REC_POINTEREVENT",
  66.     REC_RECTEXCLUDE, "REC_RECTEXCLUDE",
  67.     REC_RECTBOUND, "REC_RECTBOUND",
  68.     REC_RESULTMODE, "REC_RESULTMODE",
  69.     REC_TERMBOUND, "REC_TERMBOUND",
  70.     REC_TERMEX, "REC_TERMEX",
  71.     REC_TERMOEM, "REC_TERMOEM",
  72.     REC_TERMPENUP, "REC_TERMPENUP",
  73.     REC_TERMRANGE, "REC_TERMRANGE",
  74.     REC_TERMTIMEOUT, "REC_TERMTIMEOUT", } ;
  75.  
  76. struct decodeInt rctypeResults[] = {        // RCRESULT data types  
  77.     RCRT_UNIDENTIFIED, "RCRT_UNIDENTIFIED",
  78.     RCRT_GESTURE, "RCRT_GESTURE",   
  79.     RCRT_NOSYMBOLMATCH, "RCRT_NOSYMBOLMATCH",    
  80.     RCRT_PRIVATE, "RCRT_PRIVATE",
  81.     RCRT_NORECOG, "RCRT_NORECOG",
  82.     RCRT_ALREADYPROCESSED, "RCRT_ALREADYPROCESSED",
  83.     RCRT_GESTURETRANSLATED, "RCRT_GESTURETRANSLATED",
  84.     RCRT_GESTURETOKEYS, "RCRT_GESTURETOKEYS", } ;
  85.  
  86. struct decodeSYV syvSystemValue[] = {       // system values for SYVs
  87.     SYV_BEGINOR, "SYV_BEGINOR",
  88.     SYV_EMPTY, "SYV_EMPTY",                 
  89.     SYV_ENDOR, "SYV_ENDOR",
  90.     SYV_NULL, "SYV_NULL",                   
  91.     SYV_OR, "SYV_OR",
  92.     SYV_SOFTNEWLINE, "SYV_SOFTNEWLINE",
  93.     SYV_UNKNOWN, "SYV_UNKNOWN", } ;
  94.  
  95. struct decodeSYV syvGestureValue[] = {      // gesture values for SYVs
  96.     SYV_BACKSPACE, "SYV_BACKSPACE",
  97.     SYV_CLEAR, "SYV_CLEAR",
  98.     SYV_CLEARWORD, "SYV_CLEARWORD",
  99.     SYV_COPY, "SYV_COPY",
  100.     SYV_CORRECT, "SYV_CORRECT",
  101.     SYV_CUT, "SYV_CUT",
  102.     SYV_EXTENDSELECT, "SYV_EXTENDSELECT",
  103.     SYV_PASTE, "SYV_PASTE",
  104.     SYV_RETURN, "SYV_RETURN",
  105.     SYV_SPACE, "SYV_SPACE",
  106.     SYV_TAB, "SYV_TAB",
  107.     SYV_UNDO, "SYV_UNDO",
  108.     SYV_USER, "SYV_USER", } ;
  109.  
  110. //
  111. // WinMain --- entry point from Windows.  Registers window classes,
  112. // creates windows, registers pen app, and processes messages until 
  113. // WM_QUIT received.
  114. //
  115. int PASCAL WinMain(HANDLE hInstance, 
  116.     HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  117. {
  118.     MSG msg;                     
  119.  
  120.     hInst = hInstance;                      // save this instance handle
  121.  
  122.     if(!hPrevInstance)                      // if first instance,
  123.         if(!InitApplication(hInstance))     // register window class
  124.             return(FALSE);                  // exit if couldn't register
  125.  
  126.     if(!InitInstance(hInstance, nCmdShow))  // create this instance's window
  127.     {
  128.         MessageBox(0, "Initialization failed!", "DEMO7", MB_OK|MB_ICONSTOP);
  129.         return(FALSE);
  130.     }
  131.  
  132.     RegisterPenApp(RPA_DEFAULT, TRUE);      // enable HEDIT/BEDIT controls
  133.  
  134.     while(GetMessage(&msg, NULL, 0, 0))     // while message != WM_QUIT
  135.     {
  136.         TranslateMessage(&msg);             // translate virtual key codes
  137.         DispatchMessage(&msg);              // dispatch message to window
  138.     }
  139.     return(msg.wParam);                     // return code = WM_QUIT value
  140. }
  141.  
  142. //
  143. // InitApplication --- registers window classes for this application
  144. //
  145. BOOL InitApplication(HANDLE hInstance)
  146. {
  147.     WNDCLASS  wc;
  148.     BOOL bParent;
  149.     BOOL bText;
  150.     BOOL bWrite;
  151.  
  152.     // set parameters for frame window class
  153.     wc.style = CS_HREDRAW | CS_VREDRAW;     // class style
  154.     wc.lpfnWndProc = FrameWndProc;           // class callback function
  155.     wc.cbClsExtra = 0;                      // extra per-class data
  156.     wc.cbWndExtra = 0;                      // extra per-window data
  157.     wc.hInstance = hInstance;               // handle of class owner
  158.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);     // default icon
  159.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);       // default cursor
  160.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color 
  161.     wc.lpszMenuName =  "DemoMenu";          // name of menu resource
  162.     wc.lpszClassName = szFrameClass;        // name of window class
  163.  
  164.     bParent = RegisterClass(&wc);           // register frame window class
  165.  
  166.     // set parameters for text output child window class
  167.     wc.lpfnWndProc = TextWndProc;           // class callback function
  168.     wc.hIcon = NULL;                        // default icon
  169.     wc.lpszMenuName =  NULL;                // name of menu resource
  170.     wc.lpszClassName = szTextClass;         // name of window class
  171.  
  172.     bText = RegisterClass(&wc);             // register text child class
  173.  
  174.     // set parameters for writing input child window class
  175.     wc.lpfnWndProc = WriteWndProc;          // class callback function
  176.     wc.lpszClassName = szWriteClass;        // name of window class
  177.  
  178.     bWrite = RegisterClass(&wc);            // register writing child class
  179.  
  180.     return(bParent && bText && bWrite);     // return success/failure flag
  181. }
  182.  
  183. //
  184. // InitInstance --- creates frame window for this application instance
  185. //
  186. BOOL InitInstance(HANDLE hInstance, int nCmdShow)
  187. {
  188.     hWndFrame = CreateWindow(               // create frame window
  189.         szFrameClass,                       // window class name
  190.         "Pen Windows Demo #7",              // text for title bar
  191.         WS_OVERLAPPEDWINDOW,                // window style
  192.         CW_USEDEFAULT, CW_USEDEFAULT,       // default position
  193.         CW_USEDEFAULT, CW_USEDEFAULT,       // default size
  194.         NULL,                               // no parent window
  195.         NULL,                               // use class default menu
  196.         hInstance,                          // window owner
  197.         NULL                                // unused pointer
  198.     );
  199.  
  200.     if(!hWndFrame) return(FALSE);           // error, can't create window
  201.  
  202.     ShowWindow(hWndFrame, nCmdShow);        // make frame window visible
  203.     UpdateWindow(hWndFrame);                // force WM_PAINT message
  204.     return(TRUE);                           // return success flag
  205. }
  206.  
  207. //
  208. // FrameWndProc --- callback function for application frame window
  209. //
  210. long FAR PASCAL FrameWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  211. {
  212.     switch (wMsg) 
  213.     {
  214.         case WM_CREATE:                     // creating frame window
  215.             hWndText = CreateWindow(        // create child text window
  216.                 szTextClass,                // window class name
  217.                 NULL,                       // text for title bar
  218.                 WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER,    // style
  219.                 0, 0, 0, 0,                 // position and size
  220.                 hWnd,                       // frame window is parent 
  221.                 0,                          // child window identifier
  222.                 hInst,                      // window owner
  223.                 NULL);                      // unused pointer
  224.             hWndWrite = CreateWindow(       // create child writing window
  225.                 szWriteClass,               // window class name
  226.                 NULL,                       // text for title bar
  227.                 WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER,    // style
  228.                 0, 0, 0, 0,                 // position and size
  229.                 hWnd,                       // frame window is parent 
  230.                 0,                          // child window identifier
  231.                 hInst,                      // window owner
  232.                 NULL);                      // unused pointer
  233.             break;
  234.  
  235.         case WM_SIZE:                       // resize & position children:
  236.             MoveWindow(hWndWrite,           // writing input window 
  237.                 0, 0, LOWORD(lParam)/2, HIWORD(lParam), TRUE);
  238.             MoveWindow(hWndText,            // text output window
  239.                 LOWORD(lParam)/2, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  240.             return(0);
  241.  
  242.         case WM_COMMAND:                    // menu command received,
  243.             DoCommand(hWnd, wParam);        // decode it
  244.             break;
  245.  
  246.         case WM_DESTROY:                    // window being destroyed
  247.             PostQuitMessage(0);             // force WM_QUIT message
  248.             break;
  249.  
  250.         default:                            // let Windows handle it
  251.             return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  252.     }
  253.  
  254.     return(0);
  255. }
  256.  
  257. //
  258. // TextWndProc --- callback function for child text window
  259. //
  260. long FAR PASCAL TextWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  261. {
  262.     TEXTMETRIC tm;
  263.     HDC hdc;
  264.  
  265.     switch(wMsg)
  266.     {
  267.         case WM_CREATE:                     // creating text child window
  268.             hdc = GetDC(hWnd);              // get device context
  269.             GetTextMetrics(hdc, &tm);       // get text metrics
  270.             CharX = tm.tmAveCharWidth;      // save character size
  271.             CharY = tm.tmHeight + tm.tmExternalLeading;
  272.             ReleaseDC(hWnd, hdc);           // release device context
  273.             return(0);
  274.  
  275.         case WM_SIZE:                       // resize/position in progress
  276.             CurLine = 0;                    // reset current line number
  277.             MaxLine = HIWORD(lParam)/CharY; // no. of lines in window
  278.             return(0);
  279.  
  280.         default:
  281.             return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  282.     }
  283. }
  284.  
  285. //
  286. // WriteWndProc --- callback function for child writing window
  287. //
  288. long FAR PASCAL WriteWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  289. {
  290.     RC rc;                                  // recognition context
  291.     HDC hdc;                                // device context handle
  292.     PAINTSTRUCT ps;                         // painting info structure
  293.     RECT rect;                              // receives client rectangle
  294.     REC result;                             // status from Recognize()
  295.     LPRCRESULT rcresult;                    // recognition results
  296.     char buff1[BUFMAX];                     // scratch buffer
  297.     int i;                                  // scratch variable
  298.  
  299.     switch(wMsg)
  300.     {
  301.         case WM_PAINT:                      // window needs repainting
  302.             hdc = BeginPaint(hWnd, &ps);    // get device context
  303.             GetClientRect(hWnd, &rect);     // get client rectangle
  304.             DrawText(hdc,                   // put legend in writing area
  305.                 "Writing Area", -1, &rect, 
  306.                 DT_CENTER | DT_TOP | DT_SINGLELINE);
  307.             EndPaint(hWnd, &ps);            // release device context
  308.             break;
  309.  
  310.         case WM_LBUTTONDOWN:                // "pen-down" in writing area
  311.             if(IsPenEvent(wMsg, GetMessageExtraInfo()))
  312.             {
  313.                 InvalidateRect(hWnd, NULL, TRUE);   // erase both windows
  314.                 UpdateWindow(hWnd);         
  315.                 InvalidateRect(hWndText, NULL, TRUE);   
  316.                 UpdateWindow(hWndText);         
  317.                 CurLine = 0;                // reset current line number
  318.                 InitRC(hWndWrite, &rc);     // set default RC values
  319.                 rc.hwnd = hWnd;             // this window gets the results
  320.                 rc.rglpdf[0] = NULL;        // assume no dictionary
  321.                 DisplayLine("Calling Recognize function.");
  322.                 result = Recognize(&rc);    // request pen input
  323.                 strcpy(buff1, "Recognize result: unknown.");
  324.  
  325.                 for(i = 0; i < dim(recogResults); i++)
  326.                 {                           // decode Recognize() value
  327.                     if(recogResults[i].Code == result)
  328.                         wsprintf(buff1, "Recognize result: %s.", 
  329.                             (LPSTR) recogResults[i].Name);
  330.                 }
  331.                 DisplayLine(buff1);         // display Recognize() status   
  332.             };
  333.             return(0);
  334.  
  335.         case WM_RCRESULT:                   // receiving recognition results
  336.             rcresult = (LPRCRESULT) lParam; // get pointer to results
  337.             DisplayLine("Message WM_RCRESULT received.");
  338.             switch(DisplayMode)             // display results according
  339.             {                               // to current display mode
  340.                 case IDM_RCRESULT:          
  341.                     ShowRCResult(rcresult); // RCRESULT data structure
  342.                     break;
  343.  
  344.                 case IDM_SYMGRAPH:          // symbol graph
  345.                     ShowSymbolGraph(rcresult);
  346.                     break;
  347.  
  348.                 case IDM_SYMSTRINGS:        // candidate symbol strings
  349.                     ShowSymbolStrings(rcresult);
  350.                     break;
  351.             }
  352.             return(0);
  353.  
  354.         default:
  355.             return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  356.     }
  357. }
  358.  
  359. //
  360. // ShowRCResult -- displays contents of RCRESULT data structure
  361. //
  362. void ShowRCResult(LPRCRESULT rcresult)
  363. {
  364.     char buff1[BUFMAX];                     // scratch buffer
  365.     char buff2[BUFMAX];                     // scratch buffer
  366.     int i;                                  // scratch variable
  367.  
  368.     wsprintf(buff1, "rcresult.syg.cHotSpot = %0d", rcresult->syg.cHotSpot);
  369.     DisplayLine(buff1);                     // number of valid hot spots
  370.  
  371.     wsprintf(buff1, "rcresult.syg.nFirstBox = %0d", rcresult->syg.nFirstBox);
  372.     DisplayLine(buff1);                     // box index, first result char
  373.  
  374.     wsprintf(buff1, "rcresult.syg.lpsye = %04X:%04Xh", 
  375.         HIWORD(rcresult->syg.lpsye), LOWORD(rcresult->syg.lpsye));
  376.     DisplayLine(buff1);                     // pointer to SYE nodes
  377.  
  378.     wsprintf(buff1, "rcresult.syg.cSye = %0d", rcresult->syg.cSye);
  379.     DisplayLine(buff1);                     // no. of SYEs in symbol graph
  380.  
  381.     wsprintf(buff1, "rcresult.syg.lpsyc = %04X:%04Xh", 
  382.         HIWORD(rcresult->syg.lpsyc), LOWORD(rcresult->syg.lpsyc));
  383.     DisplayLine(buff1);                     // pointer to SYC nodes
  384.  
  385.     wsprintf(buff1, "rcresult.syg.cSyc = %0d", rcresult->syg.cSyc);
  386.     DisplayLine(buff1);                     // number of SYCs 
  387.  
  388.     if(rcresult->wResultsType == RCRT_DEFAULT)  // decode result type
  389.         DisplayLine("rcresult.wResultsType = RCRT_DEFAULT");
  390.     else                                    // if not RCRT_DEFAULT,
  391.     {                                       // check each possible flag
  392.         for(i = 0; i < dim(rctypeResults); i++) 
  393.         {                                       
  394.             if(rctypeResults[i].Code & rcresult->wResultsType)
  395.             {
  396.                 wsprintf(buff1, "rcresult.wResultsType = %s", 
  397.                     (LPSTR) rctypeResults[i].Name);
  398.                 DisplayLine(buff1);             
  399.             }
  400.         }
  401.     }
  402.  
  403.     wsprintf(buff1, "rcresult.cSyv = %d", rcresult->cSyv);
  404.     DisplayLine(buff1);                     // number of symbols
  405.  
  406.     wsprintf(buff1, "rcresult.lpsyv = %04X:%04Xh", 
  407.         HIWORD(rcresult->lpsyv), LOWORD(rcresult->lpsyv));
  408.     DisplayLine(buff1);                     // pointer to symbol string
  409.  
  410.     SymbolToCharacter(rcresult->lpsyv, BUFMAX, buff2, NULL);
  411.     wsprintf(buff1, "rcresult.lpsyv -> %s", (LPSTR) buff2);
  412.     DisplayLine(buff1);                     // best bet translated string
  413.  
  414.     wsprintf(buff1, "rcresult.hSyv = %04Xh", rcresult->hSyv);
  415.     DisplayLine(buff1);                     // handle for SYV memory block
  416.  
  417.     wsprintf(buff1, "rcresult.nBaseLine = %0d", rcresult->nBaseLine);
  418.     DisplayLine(buff1);                     // baseline of written input
  419.  
  420.     wsprintf(buff1, "rcresult.nMidLine = %0d", rcresult->nMidLine);
  421.     DisplayLine(buff1);                     // midline of written input
  422.  
  423.     wsprintf(buff1, "rcresult.hpendata = %04Xh", rcresult->hpendata);
  424.     DisplayLine(buff1);                     // pen data memory block handle
  425.  
  426.     wsprintf(buff1, "rcresult.rectBoundInk = (%d, %d) - (%d, %d)",
  427.         rcresult->rectBoundInk.left, rcresult->rectBoundInk.top,
  428.         rcresult->rectBoundInk.right, rcresult->rectBoundInk.bottom);
  429.     DisplayLine(buff1);                     // bounding rectangle for ink
  430.  
  431.     wsprintf(buff1, "rcresult.pntEnd = (%d, %d)",
  432.         rcresult->pntEnd.x, rcresult->pntEnd.y);
  433.     DisplayLine(buff1);                     // recognition termination point
  434.  
  435.     wsprintf(buff1, "rcresult.lprc = %04X:%04Xh", 
  436.         HIWORD(rcresult->lprc), LOWORD(rcresult->lprc));
  437.     DisplayLine(buff1);                     // address of RC structure
  438. }
  439.  
  440. //
  441. // ShowSymbolStrings -- enumerates and displays candidate symbol strings
  442. //
  443. void ShowSymbolStrings(LPRCRESULT rcresult)
  444. {
  445.     FARPROC lpProc;                         // far pointer for callback 
  446.     char buff1[BUFMAX];                     // scratch buffer
  447.  
  448.     wsprintf(buff1, "Symbol graph has %d possible translations.",
  449.         GetSymbolCount(&(rcresult->syg)));   
  450.     DisplayLine(buff1);                     // display no. of candidates
  451.     EnumCount = 0;                          // then display each candidate
  452.     lpProc = MakeProcInstance(EnumFunc, hInst);
  453.     EnumSymbols(&(rcresult->syg), 1000, lpProc, NULL);
  454.     FreeProcInstance(lpProc);
  455. }
  456.  
  457. //
  458. // ShowSymbolGraph -- displays contents of symbol graph
  459. //
  460. void ShowSymbolGraph(LPRCRESULT rcresult)
  461. {
  462.     LPSYE lpSye = rcresult->syg.lpsye;      // first symbol element
  463.     int cSye = rcresult->syg.cSye;          // no. of symbol elements
  464.     int Level = 0;                          // SYV_BEGINOR nesting level
  465.     SYV syv;                                // current symbol value
  466.     char syvChar;                           // current character
  467.     int syvCl;                              // current confidence level
  468.     int syvType;                            // current symbol type
  469.     char buff1[BUFMAX], buff2[BUFMAX];      // scratch buffers
  470.     int i, j;                               // scratch variable
  471.     char * p;                               // scratch pointer
  472.  
  473.     SymbolToCharacter(rcresult->lpsyv, BUFMAX, buff2, NULL);
  474.     wsprintf(buff1, "Preferred translation: %s", (LPSTR) buff2);
  475.     DisplayLine(buff1);                     // best bet translated string
  476.  
  477.     DisplayLine("Start of symbol graph:");  // now dump the symbol graph
  478.  
  479.     for(i = 0; i < cSye; i++)
  480.     {                                       
  481.         syv = lpSye[i].syv;                 // get current symbol value
  482.         syvType = HIWORD(syv);              // extract symbol type
  483.         syvChar = ChSyvToAnsi(syv);         // extract character if any
  484.         syvCl = lpSye[i].cl;                // get confidence level
  485.  
  486.         switch(syvType)                     // format according to type
  487.         {
  488.             case(SYVHI_SPECIAL):            // SYV system values
  489.                 if(syv == SYV_BEGINOR)      // start of char. choice list
  490.                 {                           
  491.                     if(Level)               // if stuff already waiting 
  492.                         DisplayLine(buff1); // in buffer, display it
  493.                     p = buff1 + wsprintf(buff1, "{ ");
  494.                     Level++;                // count nesting levels
  495.                 }
  496.                 else if(syv == SYV_OR)      // choice list separator
  497.                 {
  498.                     p += wsprintf(p, " | ");
  499.                 }
  500.                 else if(syv == SYV_ENDOR)   // end of char. choice list
  501.                 {                           
  502.                     wsprintf(p, " }");
  503.                     DisplayLine(buff1);     // display choice list
  504.                     p = buff1;
  505.                     Level--;                // count nesting levels
  506.                 }
  507.                 else                        // decode & display all 
  508.                 {                           // other system SYV values
  509.                     for(j = 0; j < dim(syvSystemValue); j++)
  510.                     {                       
  511.                         if(syvSystemValue[j].Code == syv)
  512.                             DisplayLine(syvSystemValue[j].Name);
  513.                     }
  514.                 }
  515.                 break;
  516.  
  517.             case(SYVHI_ANSI):               // SYV ASCII characters
  518.                 if(syv == SYV_SPACENULL)    // format char. & conf. level
  519.                     wsprintf(buff2, "NO SPACE [%d%%]", syvCl);
  520.                 else if(syvChar == ' ')
  521.                     wsprintf(buff2, "SPACE [%d%%]", syvCl);
  522.                 else if(syvChar < ' ')
  523.                     wsprintf(buff2, "%02Xh [%d%%]", syvChar, syvCl);
  524.                 else
  525.                     wsprintf(buff2, "%c [%d%%]", syvChar, syvCl);
  526.  
  527.                 if(Level)                   // within char. choice list?
  528.                     p += wsprintf(p, "%s", (LPSTR) buff2);  // yes, append 
  529.                 else                        // no, display text now
  530.                     DisplayLine(buff2);                     
  531.                 break;
  532.  
  533.             case(SYVHI_GESTURE):            // SYV gestures
  534.                 for(j = 0; j < dim(syvGestureValue); j++)
  535.                 {                           // decode gesture value
  536.                     if(syvGestureValue[j].Code == syv)
  537.                     {                       // found match, display it
  538.                         DisplayLine(syvGestureValue[j].Name);
  539.                         break;
  540.                     }
  541.                     if(j == dim(syvGestureValue))
  542.                     {                       // no match, show hex value
  543.                         wsprintf(buff1, "gesture: %08lXh", syv);
  544.                         DisplayLine(buff1);                     
  545.                     }
  546.                 }
  547.                 break;
  548.  
  549.             case(SYVHI_KANJI):              // Kanji
  550.             case(SYVHI_SHAPE):              // shapes
  551.             case(SYVHI_UNICODE):            // Unicode
  552.             case(SYVHI_VKEY):               // virtual keys
  553.             default:                        // whatever else
  554.                 wsprintf(buff1, "type %d: %08lXh", syvType, syv);
  555.                 DisplayLine(buff1);                     
  556.         }
  557.     }
  558.     DisplayLine("End of symbol graph.");  
  559. }
  560.  
  561. // 
  562. // DisplayLine --- displays a string in the text output child window
  563. //
  564. void DisplayLine(char * szOut)
  565. {
  566.     RECT rect;
  567.     HDC hdc;
  568.  
  569.     hdc = GetDC(hWndText);                  // get device context
  570.     GetClientRect(hWndText, &rect);         // get client rectangle
  571.     if(CurLine == MaxLine)                  // at bottom of window?
  572.     {
  573.         ScrollWindow(hWndText, 0, -CharY,   // yes, scroll window up
  574.             NULL, NULL);    
  575.         UpdateWindow(hWndText);
  576.         CurLine--;
  577.     }
  578.     TextOut(hdc, 0, CurLine * CharY,        // display text in window
  579.         szOut, strlen(szOut));
  580.     CurLine++;                              // move to next line
  581.     ReleaseDC(hWndText, hdc);               // release device context
  582.     return;
  583. }
  584.  
  585. //
  586. // DoCommand --- handles menu command messages for the frame window
  587. //
  588. void DoCommand(HWND hWnd, WORD wParam)
  589. {
  590.     FARPROC lpProc;                         // far pointer to callback 
  591.     HMENU hMenu;
  592.  
  593.     switch(wParam)                          // decode it
  594.     {
  595.         case IDM_EXIT:                      // user picked File-Quit
  596.             SendMessage (hWnd, WM_CLOSE, 0, 0L);
  597.             break;
  598.  
  599.         case IDM_RCRESULT:                  // user picked a display
  600.         case IDM_SYMGRAPH:                  // format, save it and 
  601.         case IDM_SYMSTRINGS:                // check/uncheck menu items
  602.             hMenu = GetMenu(hWnd);
  603.             CheckMenuItem(hMenu, DisplayMode, MF_UNCHECKED);
  604.             DisplayMode = wParam;
  605.             CheckMenuItem(hMenu, DisplayMode, MF_CHECKED);
  606.             break;
  607.  
  608.         default:                            // unknown command, ignore it
  609.             break;
  610.     }
  611. }
  612.  
  613. //
  614. // EnumFunc --- the callback function for EnumSymbols().  During
  615. // evaluation of a symbol graph, this function is entered 
  616. // repetitively with a pointer to each candidate symbol array.
  617. // The symbol array is translated to a character string and displayed.
  618. //
  619. int FAR PASCAL EnumFunc(LPSYV lpSyv, int cSyv, VOID FAR * lpData)
  620. {
  621.     char buff1[BUFMAX];                     // scratch buffer
  622.     char buff2[BUFMAX];                     // scratch buffer
  623.  
  624.     SymbolToCharacter(lpSyv, BUFMAX,        // convert symbol string to
  625.         buff2, NULL);                       // char string and display it
  626.     wsprintf(buff1, "Translation #%d is: %s.", ++EnumCount, (LPSTR) buff2);
  627.     DisplayLine(buff1);
  628.     return(TRUE);                           // TRUE to continue enumeration
  629. }
  630.  
  631.